{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "a76668e5",
   "metadata": {},
   "source": [
    "# Run Image Similarity Search with Milvus on Different Models\n",
    "\n",
    "In this example we will run two models to generate image feature vectors and do similarity search with [Milvus](https://milvus.io/). At the same time, we will use [ONNX](https://github.com/onnx/onnx) to manage the different models(Vgg16 and Resnet50)."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "227e709d",
   "metadata": {},
   "source": [
    "## Data\n",
    "We use the [COCO animals dataset](http://cs231n.stanford.edu/coco-animals.zip), which is a smaller subset of the COCO dataset, which has 800 training images and 200 test images of 8 classes of animals: bear, bird, cat, dog, giraffe, horse, sheep, and zebra.\n",
    "\n",
    "And we extract 200 test image from it, you can download the zip file on [google drive](https://drive.google.com/file/d/1Nz67USZbz3bloUcf6PFrt7SZ7p6oMSS_/view?usp=sharing)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "2d186e2c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Archive:  coco-images.zip\n",
      "   creating: coco-images/\n",
      "  inflating: coco-images/COCO_val2014_000000374061.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000361180.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000068650.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000009548.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000337185.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000206381.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000046898.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000463588.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000235642.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000002164.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000404992.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000093639.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000453649.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000414261.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000086168.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000323116.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000384931.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000289001.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000038919.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000323851.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000467522.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000010694.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000545129.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000173693.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000316694.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000252213.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000168775.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000304481.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000515303.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000388812.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000145426.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000546210.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000028359.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000516404.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000339009.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000140783.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000107177.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000553522.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000445675.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000291861.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000372307.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000395378.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000044250.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000268927.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000441535.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000054300.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000318099.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000208003.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000529494.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000552979.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000341950.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000570115.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000557329.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000306154.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000552612.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000414819.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000481159.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000551739.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000240393.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000189885.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000262006.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000199918.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000524280.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000342499.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000022599.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000166340.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000525087.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000397518.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000391016.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000411436.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000516879.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000563056.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000019783.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000064621.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000288465.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000008128.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000434060.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000299017.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000294724.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000383678.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000328814.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000504024.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000229647.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000262092.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000271907.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000561393.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000056205.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000148034.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000042576.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000213758.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000546222.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000483038.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000290839.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000316396.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000380101.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000077479.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000323375.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000534942.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000056646.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000467675.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000174423.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000029370.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000148968.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000454576.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000037382.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000574874.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000048907.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000238602.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000366115.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000174457.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000238377.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000517832.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000517029.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000490160.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000212403.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000291664.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000379584.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000071284.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000218215.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000327872.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000161603.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000410428.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000100489.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000560266.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000127477.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000292435.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000406001.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000391829.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000513555.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000504580.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000536292.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000070079.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000259513.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000480345.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000205344.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000492407.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000553447.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000157715.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000206831.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000161557.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000231341.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000332777.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000059393.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000240751.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000461963.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000378403.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000017089.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000483836.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000159561.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000048143.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000006871.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000088225.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000100354.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000470714.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000275253.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000561670.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000195437.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000000285.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000338531.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000574725.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000308476.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000387563.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000484893.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000362289.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000044642.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000400887.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000036765.jpg  \n",
      "  inflating: coco-images/COCO_val2014_000000272008.jpg  \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  inflating: coco-images/COCO_val2014_000000498641.jpg  \r\n",
      "  inflating: coco-images/COCO_val2014_000000405962.jpg  \r\n",
      "  inflating: coco-images/COCO_val2014_000000538423.jpg  \r\n",
      "  inflating: coco-images/COCO_val2014_000000236123.jpg  \r\n",
      "  inflating: coco-images/COCO_val2014_000000530266.jpg  \r\n",
      "  inflating: coco-images/COCO_val2014_000000284594.jpg  \r\n",
      "  inflating: coco-images/COCO_val2014_000000441458.jpg  \r\n",
      "  inflating: coco-images/COCO_val2014_000000023937.jpg  \r\n",
      "  inflating: coco-images/COCO_val2014_000000504921.jpg  \r\n",
      "  inflating: coco-images/COCO_val2014_000000154028.jpg  \r\n",
      "  inflating: coco-images/COCO_val2014_000000264506.jpg  \r\n",
      "  inflating: coco-images/COCO_val2014_000000553990.jpg  \r\n",
      "  inflating: coco-images/COCO_val2014_000000002684.jpg  \r\n",
      "  inflating: coco-images/COCO_val2014_000000428116.jpg  \r\n",
      "  inflating: coco-images/COCO_val2014_000000074013.jpg  \r\n",
      "  inflating: coco-images/COCO_val2014_000000453438.jpg  \r\n",
      "  inflating: coco-images/COCO_val2014_000000489014.jpg  \r\n",
      "  inflating: coco-images/COCO_val2014_000000417946.jpg  \r\n",
      "  inflating: coco-images/COCO_val2014_000000352007.jpg  \r\n",
      "  inflating: coco-images/COCO_val2014_000000036942.jpg  \r\n",
      "  inflating: coco-images/COCO_val2014_000000493797.jpg  \r\n",
      "  inflating: coco-images/COCO_val2014_000000351903.jpg  \r\n",
      "  inflating: coco-images/COCO_val2014_000000448448.jpg  \r\n",
      "  inflating: coco-images/COCO_val2014_000000272953.jpg  \r\n",
      "  inflating: coco-images/COCO_val2014_000000409247.jpg  \r\n",
      "  inflating: coco-images/COCO_val2014_000000558181.jpg  \r\n",
      "  inflating: coco-images/COCO_val2014_000000063381.jpg  \r\n",
      "  inflating: coco-images/COCO_val2014_000000499104.jpg  \r\n",
      "  inflating: coco-images/COCO_val2014_000000371194.jpg  \r\n",
      "  inflating: coco-images/COCO_val2014_000000122213.jpg  \r\n",
      "  inflating: coco-images/COCO_val2014_000000235203.jpg  \r\n",
      "  inflating: coco-images/COCO_val2014_000000107751.jpg  \r\n"
     ]
    }
   ],
   "source": [
    "# unzip the coco-images\n",
    "! unzip coco-images.zip"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5b6cc2b4",
   "metadata": {},
   "source": [
    "## Requirement \n",
    "| Packages |  Servers |\n",
    "| --------------- | -------------- |\n",
    "| pymilvus_orm2.0.0rc1        | Milvus-2.0rc1   |\n",
    "| redis | Redis          |\n",
    "| onnx |       |\n",
    "| onnxruntime |       |\n",
    "| tensorflow |       |\n",
    "| tf2onnx |       |\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5139211d",
   "metadata": {},
   "source": [
    "## Up and running\n",
    "\n",
    "\n",
    "#### 1. Start Milvus server\n",
    "\n",
    "```bash\n",
    "wget https://raw.githubusercontent.com/milvus-io/milvus/master/deployments/docker/standalone/docker-compose.yml -O docker-compose.yml\n",
    "docker-compose up -d\n",
    "```\n",
    "\n",
    "This demo uses Milvus 2.0. Refer to the [Install Milvus](https://milvus.io/docs/v2.0.0/install_standalone-docker.md) for how to install Milvus docker. "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "73cf8e67",
   "metadata": {},
   "source": [
    "#### 2. Start Redis\n",
    "Start [Redis](https://hub.docker.com/_/redis/) with Docker container, Redis is used to store image paths and the corresponding Milvus ids."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "1fd7940f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5ca21e891835b8f43d76da32b274dc911b229fbf9b5597e8e969fd8d26a98235\r\n"
     ]
    }
   ],
   "source": [
    "! docker run -d -p 6379:6379 redis"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9d2b9c2d",
   "metadata": {},
   "source": [
    "#### 3. Install python packages"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "acdcac98",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Requirement already satisfied: onnx in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from -r requirements.txt (line 1)) (1.9.0)\n",
      "Requirement already satisfied: onnxruntime in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from -r requirements.txt (line 2)) (1.8.0)\n",
      "Requirement already satisfied: keras2onnx in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from -r requirements.txt (line 3)) (1.7.0)\n",
      "Requirement already satisfied: tensorflow in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from -r requirements.txt (line 4)) (2.3.3)\n",
      "Requirement already satisfied: tf2onnx in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from -r requirements.txt (line 5)) (1.8.5)\n",
      "Requirement already satisfied: pymilvus-orm==2.0.0rc1 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from -r requirements.txt (line 6)) (2.0.0rc1)\n",
      "Requirement already satisfied: redis in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from -r requirements.txt (line 7)) (3.5.3)\n",
      "Requirement already satisfied: pymilvus==2.0.0rc1 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from pymilvus-orm==2.0.0rc1->-r requirements.txt (line 6)) (2.0.0rc1)\n",
      "Requirement already satisfied: pandas==1.2.4 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from pymilvus-orm==2.0.0rc1->-r requirements.txt (line 6)) (1.2.4)\n",
      "Requirement already satisfied: python-dateutil>=2.7.3 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from pandas==1.2.4->pymilvus-orm==2.0.0rc1->-r requirements.txt (line 6)) (2.8.1)\n",
      "Requirement already satisfied: pytz>=2017.3 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from pandas==1.2.4->pymilvus-orm==2.0.0rc1->-r requirements.txt (line 6)) (2021.1)\n",
      "Requirement already satisfied: numpy>=1.16.5 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from pandas==1.2.4->pymilvus-orm==2.0.0rc1->-r requirements.txt (line 6)) (1.18.5)\n",
      "Requirement already satisfied: grpcio-tools<1.38.0,>=1.22.0 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from pymilvus==2.0.0rc1->pymilvus-orm==2.0.0rc1->-r requirements.txt (line 6)) (1.37.1)\n",
      "Requirement already satisfied: requests>=2.22.0 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from pymilvus==2.0.0rc1->pymilvus-orm==2.0.0rc1->-r requirements.txt (line 6)) (2.22.0)\n",
      "Requirement already satisfied: mmh3 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from pymilvus==2.0.0rc1->pymilvus-orm==2.0.0rc1->-r requirements.txt (line 6)) (2.3.1)\n",
      "Requirement already satisfied: ujson>=2.0.0 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from pymilvus==2.0.0rc1->pymilvus-orm==2.0.0rc1->-r requirements.txt (line 6)) (4.0.2)\n",
      "Requirement already satisfied: grpcio<1.38.0,>=1.22.0 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from pymilvus==2.0.0rc1->pymilvus-orm==2.0.0rc1->-r requirements.txt (line 6)) (1.37.1)\n",
      "Requirement already satisfied: six>=1.5.2 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from grpcio<1.38.0,>=1.22.0->pymilvus==2.0.0rc1->pymilvus-orm==2.0.0rc1->-r requirements.txt (line 6)) (1.16.0)\n",
      "Requirement already satisfied: setuptools in /Users/chenshiyu/.local/lib/python3.8/site-packages (from grpcio-tools<1.38.0,>=1.22.0->pymilvus==2.0.0rc1->pymilvus-orm==2.0.0rc1->-r requirements.txt (line 6)) (57.0.0)\n",
      "Requirement already satisfied: protobuf<4.0dev,>=3.5.0.post1 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from grpcio-tools<1.38.0,>=1.22.0->pymilvus==2.0.0rc1->pymilvus-orm==2.0.0rc1->-r requirements.txt (line 6)) (3.17.3)\n",
      "Requirement already satisfied: idna<2.9,>=2.5 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from requests>=2.22.0->pymilvus==2.0.0rc1->pymilvus-orm==2.0.0rc1->-r requirements.txt (line 6)) (2.8)\n",
      "Requirement already satisfied: certifi>=2017.4.17 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from requests>=2.22.0->pymilvus==2.0.0rc1->pymilvus-orm==2.0.0rc1->-r requirements.txt (line 6)) (2021.5.30)\n",
      "Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from requests>=2.22.0->pymilvus==2.0.0rc1->pymilvus-orm==2.0.0rc1->-r requirements.txt (line 6)) (1.25.11)\n",
      "Requirement already satisfied: chardet<3.1.0,>=3.0.2 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from requests>=2.22.0->pymilvus==2.0.0rc1->pymilvus-orm==2.0.0rc1->-r requirements.txt (line 6)) (3.0.4)\n",
      "Requirement already satisfied: typing-extensions>=3.6.2.1 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from onnx->-r requirements.txt (line 1)) (3.10.0.0)\n",
      "Requirement already satisfied: flatbuffers in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from onnxruntime->-r requirements.txt (line 2)) (1.12)\n",
      "Requirement already satisfied: fire in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from keras2onnx->-r requirements.txt (line 3)) (0.4.0)\n",
      "Requirement already satisfied: onnxconverter-common>=1.7.0 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from keras2onnx->-r requirements.txt (line 3)) (1.8.1)\n",
      "Requirement already satisfied: google-pasta>=0.1.8 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from tensorflow->-r requirements.txt (line 4)) (0.2.0)\n",
      "Requirement already satisfied: keras-preprocessing<1.2,>=1.1.1 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from tensorflow->-r requirements.txt (line 4)) (1.1.2)\n",
      "Requirement already satisfied: tensorflow-estimator<2.4.0,>=2.3.0 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from tensorflow->-r requirements.txt (line 4)) (2.3.0)\n",
      "Requirement already satisfied: opt-einsum>=2.3.2 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from tensorflow->-r requirements.txt (line 4)) (3.3.0)\n",
      "Requirement already satisfied: wrapt>=1.11.1 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from tensorflow->-r requirements.txt (line 4)) (1.12.1)\n",
      "Requirement already satisfied: h5py<2.11.0,>=2.10.0 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from tensorflow->-r requirements.txt (line 4)) (2.10.0)\n",
      "Requirement already satisfied: astunparse==1.6.3 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from tensorflow->-r requirements.txt (line 4)) (1.6.3)\n",
      "Requirement already satisfied: absl-py>=0.7.0 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from tensorflow->-r requirements.txt (line 4)) (0.13.0)\n",
      "Requirement already satisfied: wheel>=0.26 in /Users/chenshiyu/.local/lib/python3.8/site-packages (from tensorflow->-r requirements.txt (line 4)) (0.36.2)\n",
      "Requirement already satisfied: tensorboard<3,>=2.3.0 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from tensorflow->-r requirements.txt (line 4)) (2.5.0)\n",
      "Requirement already satisfied: termcolor>=1.1.0 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from tensorflow->-r requirements.txt (line 4)) (1.1.0)\n",
      "Requirement already satisfied: gast==0.3.3 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from tensorflow->-r requirements.txt (line 4)) (0.3.3)\n",
      "Requirement already satisfied: google-auth<2,>=1.6.3 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from tensorboard<3,>=2.3.0->tensorflow->-r requirements.txt (line 4)) (1.32.0)\n",
      "Requirement already satisfied: werkzeug>=0.11.15 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from tensorboard<3,>=2.3.0->tensorflow->-r requirements.txt (line 4)) (2.0.1)\n",
      "Requirement already satisfied: tensorboard-data-server<0.7.0,>=0.6.0 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from tensorboard<3,>=2.3.0->tensorflow->-r requirements.txt (line 4)) (0.6.1)\n",
      "Requirement already satisfied: google-auth-oauthlib<0.5,>=0.4.1 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from tensorboard<3,>=2.3.0->tensorflow->-r requirements.txt (line 4)) (0.4.4)\n",
      "Requirement already satisfied: tensorboard-plugin-wit>=1.6.0 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from tensorboard<3,>=2.3.0->tensorflow->-r requirements.txt (line 4)) (1.8.0)\n",
      "Requirement already satisfied: markdown>=2.6.8 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from tensorboard<3,>=2.3.0->tensorflow->-r requirements.txt (line 4)) (3.3.4)\n",
      "Requirement already satisfied: pyasn1-modules>=0.2.1 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from google-auth<2,>=1.6.3->tensorboard<3,>=2.3.0->tensorflow->-r requirements.txt (line 4)) (0.2.8)\n",
      "Requirement already satisfied: cachetools<5.0,>=2.0.0 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from google-auth<2,>=1.6.3->tensorboard<3,>=2.3.0->tensorflow->-r requirements.txt (line 4)) (4.2.2)\n",
      "Requirement already satisfied: rsa<5,>=3.1.4 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from google-auth<2,>=1.6.3->tensorboard<3,>=2.3.0->tensorflow->-r requirements.txt (line 4)) (4.7.2)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Requirement already satisfied: requests-oauthlib>=0.7.0 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from google-auth-oauthlib<0.5,>=0.4.1->tensorboard<3,>=2.3.0->tensorflow->-r requirements.txt (line 4)) (1.3.0)\r\n",
      "Requirement already satisfied: pyasn1<0.5.0,>=0.4.6 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from pyasn1-modules>=0.2.1->google-auth<2,>=1.6.3->tensorboard<3,>=2.3.0->tensorflow->-r requirements.txt (line 4)) (0.4.8)\r\n",
      "Requirement already satisfied: oauthlib>=3.0.0 in /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages (from requests-oauthlib>=0.7.0->google-auth-oauthlib<0.5,>=0.4.1->tensorboard<3,>=2.3.0->tensorflow->-r requirements.txt (line 4)) (3.1.1)\r\n"
     ]
    }
   ],
   "source": [
    "! pip install -r requirements.txt"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "00fd7b2d",
   "metadata": {},
   "source": [
    "## Code Overview\n",
    "Once the environment is ready, we can start running the code. Let's start a similar image search together."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f8f97b30",
   "metadata": {},
   "source": [
    "#### 1. Load ResNet50 model and covert it to ONNX\n",
    "The first step is to extract the feature vector of the image, as mentioned earlier we will run it using two models, one is the ResNet50 model based Keras and the other is the VGG16 model.\n",
    "\n",
    "As you will see in the code below, VGG16 is a pre-trained model in ONNX format, so we can convert ResNet50 to ONNX format as well to facilitate uniform use later."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "df7841ee",
   "metadata": {},
   "outputs": [],
   "source": [
    "import onnxruntime\n",
    "import keras2onnx\n",
    "import numpy as np\n",
    "from numpy import linalg as LA\n",
    "from keras.applications.resnet50 import ResNet50\n",
    "from keras.preprocessing import image\n",
    "from keras.applications.resnet50 import preprocess_input\n",
    "import tensorflow as tf\n",
    "import os"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "12deb1ce",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:From /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages/tensorflow/python/training/tracking/tracking.py:111: Model.state_updates (from tensorflow.python.keras.engine.training) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "This property should not be used in TensorFlow 2.0, as updates are applied automatically.\n",
      "WARNING:tensorflow:From /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages/tensorflow/python/training/tracking/tracking.py:111: Layer.updates (from tensorflow.python.keras.engine.base_layer) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "This property should not be used in TensorFlow 2.0, as updates are applied automatically.\n",
      "INFO:tensorflow:Assets written to: keras_resnet50_model/assets\n"
     ]
    }
   ],
   "source": [
    "# load keras-resnet50 model and save as a floder\n",
    "model_resnet50 = ResNet50(include_top=False, pooling='max', weights='imagenet')\n",
    "tf.saved_model.save(model_resnet50, \"keras_resnet50_model\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "9c1e4fa9",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "/Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/runpy.py:127: RuntimeWarning: 'tf2onnx.convert' found in sys.modules after import of package 'tf2onnx', but prior to execution of 'tf2onnx.convert'; this may result in unpredictable behaviour\n",
      "  warn(RuntimeWarning(msg))\n",
      "2021-07-05 10:30:22,258 - WARNING - '--tag' not specified for saved_model. Using --tag serve\n",
      "2021-07-05 10:30:26,238 - INFO - Signatures found in model: [serving_default].\n",
      "2021-07-05 10:30:26,238 - WARNING - '--signature_def' not specified, using first signature: serving_default\n",
      "2021-07-05 10:30:26,238 - INFO - Output names: ['max_pool']\n",
      "WARNING:tensorflow:From /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages/tf2onnx/tf_loader.py:603: extract_sub_graph (from tensorflow.python.framework.graph_util_impl) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Use `tf.compat.v1.graph_util.extract_sub_graph`\n",
      "2021-07-05 10:30:29,021 - WARNING - From /Users/chenshiyu/miniconda3/envs/milvus2_0/lib/python3.8/site-packages/tf2onnx/tf_loader.py:603: extract_sub_graph (from tensorflow.python.framework.graph_util_impl) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Use `tf.compat.v1.graph_util.extract_sub_graph`\n",
      "2021-07-05 10:30:30,939 - INFO - Using tensorflow=2.3.3, onnx=1.9.0, tf2onnx=1.8.5/50049d\n",
      "2021-07-05 10:30:30,939 - INFO - Using opset <onnx, 9>\n",
      "2021-07-05 10:30:32,469 - INFO - Computed 0 values for constant folding\n",
      "2021-07-05 10:30:37,392 - INFO - Optimizing ONNX model\n",
      "2021-07-05 10:30:41,038 - INFO - After optimization: Add -1 (17->16), BatchNormalization -53 (53->0), Const -162 (268->106), GlobalMaxPool +1 (0->1), Identity -57 (57->0), ReduceMax -1 (1->0), Squeeze +1 (0->1), Transpose -213 (214->1)\n",
      "2021-07-05 10:30:41,188 - INFO - \n",
      "2021-07-05 10:30:41,188 - INFO - Successfully converted TensorFlow model keras_resnet50_model to ONNX\n",
      "2021-07-05 10:30:41,188 - INFO - Model inputs: ['input_1:0']\n",
      "2021-07-05 10:30:41,188 - INFO - Model outputs: ['max_pool']\n",
      "2021-07-05 10:30:41,188 - INFO - ONNX model is saved at onnx_resnet50.onnx\n"
     ]
    }
   ],
   "source": [
    "# convert resnet50 model to onnx\n",
    "! python -m tf2onnx.convert --saved-model \"keras_resnet50_model\" --output \"onnx_resnet50.onnx\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0a086dd3",
   "metadata": {},
   "source": [
    "#### 2. Get the image embeddings with onnx model(ResNet50&VGG16)\n",
    "Next we will use the two ONNX format models to generate feature vectors. And it can be seen in the following code, both the ResNet50 model and VGG16 generate different vectors, and they do not even have the same dimensionality, Resnet50 is 2048 dimensions and vgg16 is 512 dimensions.\n",
    "\n",
    "You can download the `onnx_vgg16.onnx` file om google drive: https://drive.google.com/file/d/1QRVlLD9qgbY2K8ezM83BYyvnQZVCKuTO/view?usp=sharing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "fbbfa0c2",
   "metadata": {},
   "outputs": [],
   "source": [
    "# get the image vectors with onnx model\n",
    "def get_onnx_vectors(onnx_model, img_path):\n",
    "    img = image.load_img(img_path, target_size=(224, 224))\n",
    "    x = image.img_to_array(img)\n",
    "    x = np.expand_dims(x, axis=0)\n",
    "    x = preprocess_input(x)\n",
    "    \n",
    "    sess = onnxruntime.InferenceSession(onnx_model)\n",
    "    x = x if isinstance(x, list) else [x]\n",
    "    feed = dict([(input.name, x[n]) for n, input in enumerate(sess.get_inputs())])\n",
    "    feat = sess.run(None, feed)[0]\n",
    "    \n",
    "    norm_feat = feat[0] / LA.norm(feat[0])\n",
    "    norm_feat = [i.item() for i in norm_feat]\n",
    "    return norm_feat"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "bd94ce41",
   "metadata": {},
   "outputs": [],
   "source": [
    "# try to generate vectors with ResNet50 and prepared VGG16 ONNX model\n",
    "vec_resnet = get_onnx_vectors(\"onnx_resnet50.onnx\", \"./pic/example.jpg\")\n",
    "vec_vgg = get_onnx_vectors(\"onnx_vgg16.onnx\", \"./pic/example.jpg\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "32f2b26d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The dimensions of ResNet50:  2048\n",
      "The dimensions of VGG16:  512\n"
     ]
    }
   ],
   "source": [
    "# show the dimension of different models\n",
    "print(\"The dimensions of ResNet50: \", len(vec_resnet))\n",
    "print(\"The dimensions of VGG16: \", len(vec_vgg))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "0efe5d18",
   "metadata": {},
   "outputs": [],
   "source": [
    "# generate the vectors batchs with the coco-images dataset\n",
    "def read_all_images(onnx_model, img_directory):\n",
    "    images = os.listdir(img_directory)\n",
    "    images.sort()\n",
    "    vectors = []\n",
    "    for image in images:\n",
    "        vec = get_onnx_vectors(onnx_model, img_directory + '/' + image)\n",
    "        vectors.append(vec)\n",
    "    return vectors"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "fb9b3338",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "200\n"
     ]
    }
   ],
   "source": [
    "# it will take about one minute\n",
    "IMG_DICT = 'coco-images'\n",
    "resnet_vectors = read_all_images(\"onnx_resnet50.onnx\", IMG_DICT)\n",
    "print(len(resnet_vectors))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "751f7877",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "200\n"
     ]
    }
   ],
   "source": [
    "# it will take about one minute\n",
    "vgg_vectors = read_all_images(\"onnx_vgg16.onnx\", IMG_DICT)\n",
    "print(len(vgg_vectors))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0e97e855",
   "metadata": {},
   "source": [
    "#### 3. Create collection and insert the vectors to Milvus\n",
    "In the previous section we generate the feature vectors by the model, next we can process the vectors.\n",
    "\n",
    "Milvus is an open source vector search engine, we can store and retrieve the vectors in Milvus, we first have to create the collection and insert the data."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "1b242e2b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<pymilvus.client.stub.Milvus at 0x7f9f60db7d90>"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# connect to Milvus server\n",
    "from pymilvus_orm import *\n",
    "connections.connect(host=\"127.0.0.1\", port=19530)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "85db1a44",
   "metadata": {},
   "outputs": [],
   "source": [
    "resnet_collection_name = \"resnet_img_search\"\n",
    "resnet_VECTOR_DIMENSION = 2048\n",
    "resnet_fields = [\n",
    "    schema.FieldSchema(name=\"id\", dtype=DataType.INT64, is_primary=True, auto_id=True),\n",
    "    schema.FieldSchema(name=\"vector\", dtype=DataType.FLOAT_VECTOR, dim=resnet_VECTOR_DIMENSION)\n",
    "]\n",
    "\n",
    "vgg_collection_name = \"vgg_img_search\"\n",
    "vgg_VECTOR_DIMENSION = 512\n",
    "vgg_fields = [\n",
    "    schema.FieldSchema(name=\"id\", dtype=DataType.INT64, is_primary=True, auto_id=True),\n",
    "    schema.FieldSchema(name=\"vector\", dtype=DataType.FLOAT_VECTOR, dim=vgg_VECTOR_DIMENSION)\n",
    "]\n",
    "\n",
    "TOP_K = 5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7a0144a3",
   "metadata": {},
   "outputs": [],
   "source": [
    "#Creat a collection\n",
    "\n",
    "resnet_schema = schema.CollectionSchema(fields=resnet_fields, description=\"Resnet test collection\")\n",
    "resnet_collection = Collection(name=resnet_collection_name, schema=resnet_schema)\n",
    "\n",
    "vgg_schema = schema.CollectionSchema(fields=vgg_fields, description=\"Vgg test collection\")\n",
    "vgg_collection = Collection(name=vgg_collection_name, schema=vgg_schema)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "654c1cab",
   "metadata": {},
   "outputs": [],
   "source": [
    "# insert data to Milvus and return ids\n",
    "resnet_mr = resnet_collection.insert([resnet_vectors])\n",
    "resnet_collection.load()\n",
    "resnet_ids = resnet_mr.primary_keys\n",
    "print(\"Insert resnet vector to Milvus and the len:\", len(resnet_ids))\n",
    "\n",
    "vgg_mr = vgg_collection.insert([vgg_vectors])\n",
    "vgg_collection.load()\n",
    "vgg_ids = vgg_mr.primary_keys\n",
    "print(\"Insert vgg vector to Milvus and the len:\", len(vgg_ids))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "52b15b8c",
   "metadata": {},
   "source": [
    "#### 4. Insert the image and ids to Reids\n",
    "After the vectors of the images are stored in Milvus, the corresponding ids are generated, and the next step is to store the correspondence between the ids and the image paths in Redis."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5e4003a1",
   "metadata": {},
   "outputs": [],
   "source": [
    "# connect to Redis\n",
    "import redis\n",
    "red = redis.Redis(host = '127.0.0.1', port=6379, db=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f92914f0",
   "metadata": {},
   "outputs": [],
   "source": [
    "def img_ids_to_redis(img_directory, res_ids):\n",
    "    images = os.listdir(img_directory)\n",
    "    images.sort()\n",
    "    for img, ids in zip(images, res_ids):\n",
    "        red.set(ids, img)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "76705480",
   "metadata": {},
   "outputs": [],
   "source": [
    "img_ids_to_redis(IMG_DICT, resnet_ids)\n",
    "img_ids_to_redis(IMG_DICT, vgg_ids)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4c15637a",
   "metadata": {},
   "source": [
    "#### 5. Search the similarity images\n",
    "Then we can retrieve an image in Milvus, and Milvus will return the most similar image id, and then get the image according to the id in Redis."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "946171af",
   "metadata": {},
   "outputs": [],
   "source": [
    "# search in Milvus and return the similarly results with ids\n",
    "def search_in_milvus(collection, search_vector):\n",
    "    search_params = {\"metric_type\": \"L2\", \"params\": {\"nprobe\": 32}}\n",
    "    results = collection.search([search_vector], \"vector\", param=search_params, limit=10, expr=None)\n",
    "    re_ids = [x.id for x in results[0]]\n",
    "    re_distance = [x.distance for x in results[0]]\n",
    "    return re_ids, re_distance"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "732a10b3",
   "metadata": {},
   "outputs": [],
   "source": [
    "# get the images according the result ids\n",
    "def get_sim_imgs(collection, search_vector):\n",
    "    ids, distance = search_in_milvus(collection, search_vector)\n",
    "    img = [red.get(i).decode(\"utf-8\") for i in ids]\n",
    "    return ids, distance, img"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f8a96490",
   "metadata": {},
   "outputs": [],
   "source": [
    "resnet_ids, resnet_distance, resnet_img =  get_sim_imgs(resnet_collection, vec_resnet)\n",
    "vgg_ids, vgg_distance, vgg_img =  get_sim_imgs(vgg_collection, vec_vgg)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7cd2740e",
   "metadata": {},
   "source": [
    "#### 6. Show the results\n",
    "Finally we get the most similar image results(id, distance and image) to the target image, and we can see together how the different models retrieve the results.\n",
    "\n",
    "We can see that the first image of the retrieval result is our target image (because the distance is 0), and the first 5 results look the same but the distance is not the same. It can be seen that the retrieval effect of VGG16 and ResNet50 is about the same, but of course you can use more and larger data to retrieve, and the effect may be different."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cef337bb",
   "metadata": {},
   "outputs": [],
   "source": [
    "from IPython.display import Image, display\n",
    "def show_results(img, ids=None, distance=None):\n",
    "    for i in range(len(img)):\n",
    "        print(ids[i], distance[i])\n",
    "        x = Image(filename=IMG_DICT+'/'+resnet_img[i]) \n",
    "        display(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bfce5a14",
   "metadata": {},
   "outputs": [],
   "source": [
    "show_results(resnet_img, resnet_ids, resnet_distance)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0925e3f3",
   "metadata": {},
   "outputs": [],
   "source": [
    "show_results(vgg_img, vgg_ids, vgg_distance)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "milvus20",
   "language": "python",
   "name": "milvus2_0"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
